#!/usr/bin/python
# -*- coding: utf-8 -*-

#This file is part of pyLot library.
#
# pyLot is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyLot is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pyLot.  If not, see <http://www.gnu.org/licenses/>.

__author__ = u'Pierre Puiseux, Guillaume Baty'
__copyright__ = u"Copyright 2011-2012 (C) andheo, Université de Pau et des Pays de l'Adour"
__credits__ = [u'Pierre Puiseux', u'Guillaume Baty']
__license__ = "GNU Lesser General Public License"

u"""
pyLot widget interface.
  - 03-2010, Pierre Puiseux, Guillaume Baty
  
Université de Pau et des Pays de l'Adour, INRIA
"""

__all__ = [u'WidgetInterface']

import sys

from Qt4.QtCore import SIGNAL
from pyLot.core import (Plugin, uprint, make_aliases)

from _pylot.qtgui.tools import fill
from _pylot.qtgui.interfaces.basewidgetinterface import BaseWidgetInterface

import warnings

class WidgetInterface(BaseWidgetInterface):

  def __init__(self, handler=None):
    BaseWidgetInterface.__init__(self, handler=handler)
    warnings.warn('Deprecated since 2012-03-14, use Widget instead', DeprecationWarning)

  def _setpref(self, preferences):
    self._pref = preferences
  tool_bars = property(fget=lambda self:self._tool_bars)
  pref = property(fget=lambda self:self._pref, fset=_setpref)

  # ============================================================================
  # Methods to implement
  # ============================================================================

  def _init(self):
    pass

  def _quit(self):
    return True

  def _switchUserLevel(self, level):
    pass

  def _fillToolBars(self, level):
    u"""
    Clears and fills toolbars depending on level.
    
    Example ::
      self._fill(self.tool_bar_pylot, [
        self.action_all_levels,
        (self.action_expert, u'expert')
        ])
    """

  def _fillMenus(self, level):
    u"""
    Clears and fills menus depending on level.
    
    Example ::
      self._fill(self.menu_pylot, [
        self.action_all_levels,
        (self.action_expert, u'expert')
        ])
    """

  def _readSettings(self, settings, common):
    pass

  def _writeSettings(self, settings, common):
    pass

  # ============================================================================
  # Widget Creation
  # ============================================================================

  def _fill(self, widget, actions, clear=True):
    u"""
    Fills widget with actions.
    Widget must be a QToolBar, a QMenuBar or QMenu.
    "actions" is a list of actions.

    Available type for actions are :
      - simple action: QAction or QMenu
      - couple (simple action, level) (see switchUserLevel)
      - u'-' (separator)
      
    :param widget: widget you want to fill
    :type widget: see description
    :param actions: list of actions
    :type widget: obj:`list`, see description
    """
    fill(widget, actions, self.handler.level, clear=clear)

  # ============================================================================
  # Adding plugins, menus, ...
  # ============================================================================

  def addPlugin(self, name, handler=None, plugin_id=None, auto_fill_widget=True,
                aliases=[]):
    u"""
    :param name: name of plugin directory (NOT path)
    :type name: :obj:`unicode`
    :param handler: instance of handler corresponding to plugin
    :param auto_fill_widget: if True, adds automatically menus, toolbars, ... to current GUI
    """
    if handler is None :
      #TODO: meilleure desc !!!
      uprint(tr_(u'Explication rôle du handler'), file=sys.stderr)
      raise ValueError

    module = Plugin(name)
    gui = module.gui_class(handler=handler)

    if plugin_id is None :
      plugin_id = gui.handler.name

    if plugin_id in self._children :
      raise NameError, tr_(u'A plugin named "%s" yet exists, please change "plugin_id" argument') % (plugin_id)
    else :
      self._children[plugin_id] = gui

    make_aliases(gui, self, aliases)
    return gui

  def addMenu_(self, menu, name=None):
    u"""
    Adds QMenu "menu" to widget.
    Adding menu with this method allows automatic treatments like menu 
    generation.

    See also
    :meth:`~_pylot.qtgui.interfaces.widgetinterface.WidgetInterface.removeMenu_`
    """
    if isinstance(name, basestring) :
      menu.setObjectName(name)
    if menu not in self.menus :
      self.menus.append(menu)
    return menu

  def removeMenu_(self, menu):
    u"""
    Removes menu. 
    
    See also
    :meth:`~_pylot.qtgui.interfaces.widgetinterface.WidgetInterface.addMenu_`
    """
    if menu in self.menus :
      self.menus.remove(menu)

  def addToolBar_(self, tool_bar):
    u"""
    Adds QToolBar "tool_bar" to widget.
    Adding menu with this method allows automatic treatments like adding all
    tool_bars to mainwindow.

    See also
    :meth:`~_pylot.qtgui.interfaces.widgetinterface.WidgetInterface.removeToolBar_`
    """
    if tool_bar not in self.tool_bars :
      self.tool_bars.append(tool_bar)
    return tool_bar

  def removeToolBar_(self, tool_bar):
    u"""
    Remove tool_bar.
    See also
    :meth:`~_pylot.qtgui.interfaces.widgetinterface.WidgetInterface.addToolBar_`
    """
    if tool_bar in self.tool_bars :
      self.tool_bars.remove(tool_bar)

  def append(self, widget):
    if widget not in self._widgets :
      self._widgets.append(widget)

  def removepyLotWidget(self, widget):
    if widget in self._widgets :
      self._widgets.remove(widget)

  def getChildren(self):
    return self._children

  def getpyLotWidgets(self):
    return self._widgets

  def getDockableWidgets(self):
    return [(self, u'user')]


  def _createActions(self):
    u"""
    Les actions du widget ...
    Actions are typed of QAction
    
    .. warning ::
      Action may be defined here or in designer file.
      Texts and titles must be defined in _translate methods, don't forget do it !

    Good example::
      self.action_quit = QAction()
    
    Wrong example::
      self.action_quit = QAction(u'Quit')
    """

  def _createMenus(self):
    u"""
    Creates empty QMenu(s). This method must be called in widget __init__
  
    L'affichage du menu est assuré par l'appelant.
    Le widget UiWidgetInterface n'affiche rien.
    
    This method must fill self.menus dict (see constructor)

    .. warning ::
      Texts and titles must be defined in _translate methods, don't forget do it !
      You must set an object name, else it may cause problems.

    Good example ::  
      self.menu_xyz = QMenu()
      menu.setObjectName(u'MenuXyz')
      self.addMenu_(self.menu_xyz)

    Wrong example ::
      self.menu_xyz = QMenu(u'Menu')
    """

  def _createToolBars(self):
    u"""
    Creates empty QToolBar(s). This method must be called in widget __init__
  
    L'affichage de la tool_bar est assuré par l'appelant.
    Le widget UiWidgetInterface n'affiche rien.

    .. warning ::
      Texts and titles must be defined in _translate methods, don't forget do it !
      You must set an object name, else it may cause problems and tool_bar state
      will not be saved.

    Example ::
  
      self.tool_bar_pylot = QToolBar()
      self.tool_bar_pylot.setObjectName(u"tool_bar_pylot")
      self.tool_bar_pylot.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
      self.addToolBar_(self.tool_bar_pylot)
    """

  def _createPreferences(self):
    u"""
    Creates preferences widget

    .. note ::
      You should implement this class

    Example ::
    
      pref = GuiPrefWidget()
      self.pref = pref
    """


  # ============================================================================
  # Widget Settings
  # ============================================================================
  def readSettings(self, settings, common=None):
    u"""
    .. warning ::
      Instructions must be defined in private method _readSettings.
      Only inherits this method if you really know what you are talking about.

    :param settings: setting object
    :type settings: QSettings
    """
    if common is None :
      common = settings

    for module in self._children.values() + self._widgets :
      module.readSettings(settings, common)

    if self.pref :
      self.pref.readSettings(settings, common)

    self._readSettings(settings, common)

  def writeSettings(self, settings, common=None):
    u"""
    .. warning ::
      Instructions must be defined in private method _writeSettings.
      Only inherits this method if you really know what you are talking about.

    :param settings: setting object where you want to write
    :type settings: QSettings
    """
    if common is None :
      common = settings

    for module in self._children.values() + self._widgets :
      module.writeSettings(settings, common)

    if self.pref :
      self.pref.writeSettings(settings, common)

    self._writeSettings(settings, common)

  def init(self):
    u"""
    .. warning ::
      Instructions must be defined in private method _init.
      Only inherits this method if you really know what you are talking about.
    """
    for module in self._children.values() + self._widgets :
      module.init()

    if self.pref :
      self.pref.init()

    return self._init()

  def quit(self):
    u"""
    .. warning ::
      Instructions must be defined in private method _quit.
      Only inherits this method if you really know what you are talking about.
    """
    for module in self._children.values() + self._widgets :
      module.quit()

    if self.pref :
      self.pref.quit()

    return self._quit()

  def requestUndock(self):
    self.emit(SIGNAL('undockRequested'), self)

  def requestRedock(self, level=u'user'):
    if self.handler.goodLevel(level):
      self.emit(SIGNAL('redockRequested'), self)

  # ============================================================================
  # Widget Dynamic Changes
  # ============================================================================

  def switchUserLevel(self, level=None):
    u"""
    Switches display level.
    This method calls recursivly switchUserLevel method of all children's 
    widgets and preferences.

    If level is not defined, it uses handler level.

    .. warning ::

      Level switching instructions must be defined in following private methods:
        - _fillMenus
        - _fillToolBars
        - _switchUserLevel
  
      Only inherits this method if you really know what you are talking about.
    """
    if level :
      self.handler.switchUserLevel(level)
    level = self.handler.level

    for module in self._children.values() + self._widgets :
      module.switchUserLevel(level)

    if self.pref :
      self.pref.switchUserLevel(level)

    self._fillMenus(level)
    self._fillToolBars(level)
    self._switchUserLevel(level)

if  __name__ == u"__main__":
  pass
